package net.soe;

import scala.Math;


object __Shape {
abstract class _Shape  
case class Rectangle(a: Side, b:Side) extends _Shape
case class Ellipse(a: Radius, b:Radius) extends _Shape
case class RtTriangle(a: Side, b:Side) extends _Shape
case class Polygon(a: List[Vertex]) extends _Shape


// Float was giving me grief in the sqrt function, it needed Double or Int!
type Radius = Double
type Side = Double    
type Vertex = (Double, Double)

def square(a: Side) : _Shape = Rectangle(a, a)
def circle(a: Radius) : _Shape = Ellipse(a,a)

def triArea( v1: Vertex, v2: Vertex, v3: Vertex) : Double =  {
   def a = distBetween(v1, v2)
   def b = distBetween(v2, v3)
   def c = distBetween(v3, v1)
   def s = 0.5*(a+b+c)
   Math.sqrt (s*(s-a)*(s-b)*(s-c))
}

def distBetween( v1:Vertex, v2: Vertex) : Double = {
  def x1 = v1._1
  def y1 = v1._2
  def x2 = v2._1
  def y2 = v2._2
  Math.sqrt(sqr(x1-x2) + sqr(y1-y2))
}


 // ToDo: find the Scala's square
 def sqr(x: Double) : Double = x * x 

 def area( s:_Shape): Double =  s match {
   case Rectangle(a, b) => a*b
   case RtTriangle(a, b) => a*b/2
   case Ellipse(a, b) => 3.14*a*b   // TODO: find the PI from math lib.
   case Polygon (v1::vs) =>  {
          def polyArea(verts: List[Vertex]):Double = {
             verts match {
             case(v2::v3::vss) => triArea(v1, v2, v3) + polyArea(v3::vss)
             case _ => 0   
             }       
          }
          polyArea(vs)
   }
   case _ => 0
 }
}
